#ifndef IMAGEPROCESSOR_H
#define IMAGEPROCESSOR_H
#include <QtGui>
#include "utility.h"
void GetGrayHist(float* hist,QImage*m_raw_image);

void Equalization(float*src_hist,float*dest_hist,float*map);

class ConvProcessor
{
public:
    virtual void Begin(int x,int y,int value = 0) = 0;

    virtual void Input(int i ,int j,int value,int kernel) = 0;

    virtual void OutOfBoundary(int i ,int j ,int kernel) = 0;

    virtual int Finish(){return v>255?255:(v<0?0:v);}
protected:
    int v;
};

class DilationErosion:public ConvProcessor
{
public:

    DilationErosion(bool Dilation,bool bBin = false){indicate = Dilation;bin = bBin;}

    virtual void Begin(int x,int y,int value=0){v=indicate?0:255;}

    virtual void Input(int i ,int j,int value,int kernel){
        if(!bin)
            v=!(((value+kernel)>v) ^ indicate)?value+kernel:v;
        else
            v= indicate?((value&&kernel)?255:v):(!value && kernel?0:v);
    }

    virtual void OutOfBoundary(int i ,int j ,int kernel){}

private:
    bool bin;
    bool indicate;
};

class DistanceProcessor:public ConvProcessor
{
public:
    DistanceProcessor(int width,int height){max = 0;this->width = width;Bitmap = new uchar[width*height];memset(Bitmap,0,sizeof(uchar)*width*height);}

    ~DistanceProcessor(){delete Bitmap;}

    void IterationBegin(){bEnd = true;}

    virtual void Begin(int i,int j,int value = 0){pos = i*width+j;erosion=true;}

    virtual void Input(int i ,int j,int value,int kernel){if(kernel * value == 0) erosion=false;}

    virtual void OutOfBoundary(int i ,int j ,int kernel){}

    virtual int Finish()
    {
        if(erosion)
        {
            Bitmap[pos]++;
            if(Bitmap[pos]>max)
                max = Bitmap[pos];
            bEnd = false;
            return 255;
        }
        return 0;
    }

    bool IterationEnd()
    {
        return bEnd;
    }
    uchar *Bitmap;
     int max;
private:

    bool bEnd;
    bool erosion;
    int pos;
    int width;

};

QImage DistanceTrans(QImage* m_raw_image);

QImage OpenImage(QImage*m_raw_image,float*matrix,int matrix_width,int matrix_height,bool bin = false);

QImage CloseImage(QImage*m_raw_image,float*matrix,int matrix_width,int matrix_height,bool bin = false);

QImage MorReconstruction(QImage*m_raw_image,float*matrix,int matrix_width,int matrix_height);


void ConvMatrix(uchar*raw,int width,int height,float *matrix,int matrix_width, int matrix_height,ConvProcessor* processor,
                uchar* dest=0,int center_x=-1,int center_y=-1);

QImage BinImge(QImage*m_raw_image,int threshold);

QImage ZoomImage(QImage*m_raw_image,int new_height,int new_width,short zoom_mode);

QImage ConvImage(QImage* m_raw_image,float *matrix, int matrix_width,int matrix_height,float division=1.0);

QImage ConvImage(QImage *m_raw_image, float *matrix, int matrix_width, int matrix_height,ConvProcessor *processor,
                 int matrix_origin_x=-1,int matrix_origin_y=-1);

QImage MedianFilter(QImage* m_raw_image);


typedef void (*BinaryOperation)(uchar* dest,uchar*src1,uchar*src2,void* args);

void AndOperation(uchar* dest,uchar*src1,uchar*src2,void* factor=0);

void AddOperation(uchar* dest,uchar*src1,uchar*src2,void* factor = 0);

void MultiOperation(uchar* dest,uchar*src1,uchar*src2,void* factor = 0);

void SubOperation(uchar* dest,uchar*src1,uchar*src2,void* factor = 0);

QImage BinaryImageOperation(QImage*image1,QImage*image2,BinaryOperation operation,void* args=0);




typedef void (*PointOperation)(uchar* dest,uchar*src,void* args);

void ContrastOperation(uchar* dest,uchar* src,void* args);

void GrayOperation(uchar* dest,uchar* src,void* args);

void BinOperation(uchar* dest,uchar*src,void* args);

void RemapOperation(uchar* dest,uchar*src,void*args);

void LightOperation(uchar* dest,uchar*src,void*args);

QImage PointImageOperation(QImage*image,PointOperation operation,void* args = 0);



typedef void(*BinMatrixOperation)(uchar*dest,uchar*src1,uchar* src2);

void BinAddOperation(uchar*dest,uchar*src1,uchar* src2);

void BinMinusOperation(uchar*dest,uchar*src1,uchar* src2);

void BinMatrix(uchar*src1,uchar*src2,uchar*dest,int size,BinMatrixOperation op);

int GetBaseThreshold(float* gray,int delta = 2);

int GetOstuThreshold(float* gray);

int GetThresholdEntropy(float* gray);

QImage Skeleton(QImage* m_raw_image,int*K,float*matrix,int m_w,int m_h);

QImage SkeletonRestruction(QImage* m_raw_image,int K,float*matrix,int m_w,int m_h);

#endif // IMAGEPROCESSOR_H
